package se.webbzon.boltzmann.game.npc;

import java.util.Collection;

import se.webbzon.boltzmann.collector.Collector;
import se.webbzon.boltzmann.game.character.CharacterException;
import se.webbzon.boltzmann.game.object.player.AbstractPlayerCharacter;
import se.webbzon.boltzmann.npc.AbstractNPC;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldObject;

public abstract class GameNPC extends AbstractNPC {
	
	// The default walk and run speed of the non-player game character
	private static final double defaultWalkSpeed = 1,
								defaultRunSpeed = 1.5;
	
	// A collector used to track the players in the world
	private Collector<AbstractPlayerCharacter> players;
	
	/*============================================================
	Constructors
	============================================================*/

	public GameNPC(String characterTextureSetName) throws CharacterException {
		this(0, characterTextureSetName);
	}
	
	public GameNPC(int registeredMethods, String characterTextureSetName) throws CharacterException {
		this(registeredMethods, characterTextureSetName, defaultWalkSpeed, defaultRunSpeed);
	}
	
	public GameNPC(	int registeredMethods, 
					String characterTextureSetName,
					double walkSpeed, double runSpeed) throws CharacterException {
		super(	registeredMethods | WorldObject.onCreate | WorldObject.onDestroy, 
				characterTextureSetName, walkSpeed, runSpeed);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Returns true if the non-player game character is hostile. **/
	public abstract boolean isHostile();
	
	/** Returns a synchronized collection of all players known by 
	 * the non-player character. This method is only available
	 * if the npc is created in a world area. **/
	public Collection<AbstractPlayerCharacter> getPlayers() {
		return players.getInstances();
	}
	
	/** Returns the closest player to this non-player character. **/
	public AbstractPlayerCharacter closestPlayer() {
		AbstractPlayerCharacter closestPlayer = null;
		double minDistance = Double.MAX_VALUE;
		Collection<AbstractPlayerCharacter> players = getPlayers();
		synchronized (players) {
			for (AbstractPlayerCharacter player : players) {
				final double distance = distanceTo(player);
				if (distance < minDistance) {
					closestPlayer = player;
					minDistance = distance;
				}
			}
		}
		return closestPlayer;
	}
	
	@Override public void onCreate(WorldArea world) {
		super.onCreate(world);
		players = Collector.getCollector(world, AbstractPlayerCharacter.class);
	}
	
	@Override public void onDestroy(WorldArea world) {
		players = null;
		super.onDestroy(world);
	}

}
